package com.jaynux.app;

import java.util.ArrayList;

import android.app.*;
import android.content.*;
import android.hardware.*;
import android.media.*;
import android.os.*;
import android.os.PowerManager.*;
import android.util.*;
import android.view.*;
import android.view.WindowManager.*;
import android.widget.*;

public class measureActivity extends Activity {

	public static final String TAG = "measureActivity";

	public final static int ACCELERATECONDTION = 100;

	// 다이얼로그를 출력하기 위한 변수.
	public static final int DIALOG_PROBABILITY_PROGRESS = 1;

	/*히든 오픈을 알려주는 플레그. */
	boolean row1col1Flag = false;
	boolean row1col2Flag = false;
	boolean row1col3Flag = false;
	boolean row2col1Flag = false;
	boolean row2col2Flag = true;
	boolean row2col3Flag = false;
	boolean row3col1Flag = false;
	boolean row3col2Flag = false;
	boolean row3col3Flag = false;

	/* 최종 결과값을 저장하는 배열의 INDEX 값 */
	final int SPEED_INDEX = 0;
	final int BOOSTER_INDEX =1;
	final int STEP_INDEX = 2;
	final int FINGELDISTANCEINDEX = 3;

	/* 측정의 상태들을 타나 낸다. */
	public final static int SHAKEON = 0;
	public final static int POWERON = 1;
	public final static int FINGERTOUCHON = 2;
	public final static int FINGERDISTANCEON = 3;
	public final static int ALLOFF = 4;

	public final static int PROCESSRESULT =4;

	// 프로그레스바 변수이다.
	private ProgressDialog mWriteProgressDialog;

	private TextView mMeasureText;
	private TextView mMessageText1;
	private TextView mMesaageText2;
	private TextView mValueText; 
	private TextView mNowTimeText;

	private Button mShakeButton;
	private Button mPowerButton;
	private Button mFingerTouchButton;
	private Button mFingerDistanceButton;
	private Button mApplyButton; 

	//측정을 위해 사용자에게 준비를 알리는 시간
	private int mReadyTime = 3;
	//실제 측정을 수행하는 시간
	private int mMeasureTime = 10;

	//효과음 관련 멤버들이다.
	SoundPool mPool;
	private int mTimeSound;	//시간이 지나가는 소리

	private PowerManager mPm;
	private WakeLock mWakeLock;

	int mStatus = ALLOFF;
	SensorManager mSm;

	private int mNum = 0;					// 흔들기 횟수를 저장하는 멤버
	private int mBeforValue[] = {0,0,0};	// 이전의 가속도 값을 저장한다. (해딩, 피치, 롤)
	private int mAfterValue[] = {0,0,0};	// 이후의 가속도 값을 저장한다. (해딩, 피치, 롤)
	private int mTime = 0;					// 이전과 이후를 구분 한다.
	private int mAccelerateValue;			// 가속도 변화 누적 값을 기록한다.
	private int mFingerTouchValue=0;		// 손가락 터치양을 기록 한다.
	private int mFingerDistanceValue = 0; 	// 손가락 거리이동 양을 기록 한다.
	private ArrayList<Vertex> arVertex;		// 터치한 포인트 좌표를 기록한다. 
	
	// 최종적인 결과 값을 저장한다.
	// speed, booster, step
	private int mMeasureResult[] = {0,0,0,0}; 

	// 확률 까지 적용한 최종적인 결과 저장 값이다.
	int mChanceResult[]= {0,0,0,0};
	
	int mCycle;

	//프리페어런스 변수이다.
	SharedPreferences mPref;
	SharedPreferences.Editor mEdit;
	
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.measure);

		// 위젯들 찾음
		mValueText = (TextView)findViewById(R.id.nowvaluetext);
		mNowTimeText = (TextView)findViewById(R.id.nowtimetext);
		mMessageText1 = (TextView)findViewById(R.id.messagetext1);
		mMesaageText2 = (TextView)findViewById(R.id.messagetext2);
		mMeasureText = (TextView)findViewById(R.id.measurevaluetext);

		// 시간 지나가는 소리 및 측정을 시작하는 소리
		mPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
		mTimeSound = mPool.load(this, R.raw.ddok, 1);
		
		// 터치 점을 저장하기 위한 ArrayList를 설정한다.
		arVertex = new ArrayList<Vertex>();

		// 버튼의 핸들러 연결
		mShakeButton = (Button)findViewById(R.id.shakebutton); 
		mShakeButton.setOnClickListener(mClickListener);
		mPowerButton = (Button)findViewById(R.id.powerbutton); 
		mPowerButton.setOnClickListener(mClickListener);
		mFingerTouchButton = (Button)findViewById(R.id.fingertouchbutton);
		mFingerTouchButton.setOnClickListener(mClickListener);
		mFingerDistanceButton = (Button)findViewById(R.id.fingerdistancebutton);
		mFingerDistanceButton.setOnClickListener(mClickListener);
		mApplyButton = (Button)findViewById(R.id.measureapplybutton);
		mApplyButton.setOnClickListener(mClickListener);

		// WakeLock 객체 생성
		mPm = (PowerManager)getSystemService(Context.POWER_SERVICE);
		mWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "tag");

		//하드웨어 관리자 추출
		mSm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

	}

	// 떠 있는 동안 화면 유지. 백그라운드 카운팅도 실용성 있어 카운팅 중에만 유지하는 정책은 좋지 않음
	protected void onResume() {
		super.onResume();
		//가속도 센서를 얻어온다.
		mSm.registerListener(Listner,
				mSm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_UI);
		//화면 꺼짐을 방지한다. 항상 화면은 켜져있는 상태이다.
		mWakeLock.acquire();
		
		//프리페어런스
		mPref = getSharedPreferences("preftest", 0);
		mEdit = mPref.edit();
	}

	protected void onPause() {
		super.onPause();
		/*가속도 센서 작업을 정지 시킨다. 베터리 절약을 위해서*/
		mSm.unregisterListener(Listner,
				mSm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER));
		//화면 꺼짐을 방지를 풀어준다.
		if (mWakeLock.isHeld()) {
			mWakeLock.release();
		}
	}

	Button.OnClickListener mClickListener = new View.OnClickListener() {
		public void onClick(View v) {
			Message msg;
			switch (v.getId()) {
			case R.id.shakebutton:
				// 흔들기 측정값을 저장하는 멤버를 초기화 한다.
				mNum = 0;

				//측정시간을 초기화 한다. 측정시간은 측정 방법마다 틀리다. 따라서 버튼을 누를때 설정한다.
				mMeasureTime = 10;

				//오작동 방지를 위해서 버튼을 모두 숨긴다.
				mShakeButton.setVisibility(View.INVISIBLE);
				mPowerButton.setVisibility(View.INVISIBLE);
				mFingerTouchButton.setVisibility(View.INVISIBLE);
				mFingerDistanceButton.setVisibility(View.INVISIBLE);
				mApplyButton.setVisibility(View.INVISIBLE);

				//어떤 측정모드의 시작인지를 알려주기위해 메시지에 모드를 넣어서 핸들러로 보낸다.
				msg = Message.obtain();
				msg.what = SHAKEON;
				mTimerHandler.sendMessage(msg);	
				break;

			case R.id.powerbutton:	

				// 파워 측정값을 저장하는 멤버를 초기화 한다.
				mAccelerateValue =0;

				//측정시간을 초기화 한다. 측정시간은 측정 방법마다 틀리다. 따라서 버튼을 누를때 설정한다.
				mMeasureTime = 2;			

				//오작동 방지를 위해서 버튼을 모두 숨긴다.
				mShakeButton.setVisibility(View.INVISIBLE);
				mPowerButton.setVisibility(View.INVISIBLE);
				mFingerTouchButton.setVisibility(View.INVISIBLE);
				mFingerDistanceButton.setVisibility(View.INVISIBLE);
				mApplyButton.setVisibility(View.INVISIBLE);
				
				//어떤 측정모드의 시작인지를 알려주기위해 메시지에 모드를 넣어서 핸들러로 보낸다.
				msg = Message.obtain();
				msg.what = POWERON;
				mTimerHandler.sendMessage(msg);
				break;

			case R.id.fingertouchbutton:	

				//손가락 터치 측정값을 저장하는 멤버를 초기화한다.
				mFingerTouchValue =0;		

				//측정시간을 초기화 한다. 측정시간은 측정 방법마다 틀리다. 따라서 버튼을 누를때 설정한다.
				mMeasureTime = 10;

				//오작동 방지를 위해서 버튼을 모두 숨긴다.
				mShakeButton.setVisibility(View.INVISIBLE);
				mPowerButton.setVisibility(View.INVISIBLE);
				mFingerTouchButton.setVisibility(View.INVISIBLE);
				mFingerDistanceButton.setVisibility(View.INVISIBLE);
				mApplyButton.setVisibility(View.INVISIBLE);
				
				//어떤 측정모드의 시작인지를 알려주기위해 메시지에 모드를 넣어서 핸들러로 보낸다.
				msg = Message.obtain();
				msg.what = FINGERTOUCHON;
				mTimerHandler.sendMessage(msg);
				break;
			case R.id.fingerdistancebutton:
				//손가락 거리 측정값을 저장하는 멤버를 초기화한다.
				mFingerDistanceValue = 0;
				//측정시간을 초기화 한다. 측정시간은 측정 방법마다 틀리다. 따라서 버튼을 누를때 설정한다.
				mMeasureTime = 10;
				
				//오작동 방지를 위해서 버튼을 모두 숨긴다.
				mShakeButton.setVisibility(View.INVISIBLE);
				mPowerButton.setVisibility(View.INVISIBLE);
				mFingerTouchButton.setVisibility(View.INVISIBLE);
				mFingerDistanceButton.setVisibility(View.INVISIBLE);
				mApplyButton.setVisibility(View.INVISIBLE);
				
				//어떤 측정모드의 시작인지를 알려주기위해 메시지에 모드를 넣어서 핸들러로 보낸다.
				msg = Message.obtain();
				msg.what = FINGERDISTANCEON;
				mTimerHandler.sendMessage(msg);
				break;
			case R.id.measureapplybutton:
				saveProgress(1000);
				processResultThread mProcessResultThread = new processResultThread();
				mProcessResultThread.start();
				break;
			}
		}
	};

	/* 가속도 센서를 위한 무명 클래스로 리스너를 만들 었다. */
	private SensorEventListener Listner = new SensorEventListener(){

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			// TODO Auto-generated method stub	
		}
		//리스너에 의해서 가속도센서값이 변경 되면 자동으로 호출된다.
		//가장 느린 속도인 UI 속도로 설정해도 민감도가 매우 높기떄문에 매우 빈번하게 호출되어진다.
		public void onSensorChanged(SensorEvent event) {
			// TODO Auto-generated method stub
			synchronized(this)
			{
				switch (event.sensor.getType())
				{
				case Sensor.TYPE_ACCELEROMETER:
					if(mStatus == SHAKEON){
						if(mTime == 0)
						{
							mTime = 1;
							mBeforValue[0] = (int)event.values[0];
							mBeforValue[1] = (int)event.values[1];
							mBeforValue[2] = (int)event.values[2];
						}
						else
						{
							mTime = 0;
							mAfterValue[0] = (int)event.values[0];
							mAfterValue[1] = (int)event.values[1];
							mAfterValue[2] = (int)event.values[2];
						}
						mAccelerateValue += Math.abs(mBeforValue[0] -mAfterValue[0]);
						mAccelerateValue += Math.abs(mBeforValue[1] -mAfterValue[1]);

						//누적값이 일정 수치를 넘어서면 1번 흔든것으로 판단한다.
						if(mAccelerateValue > ACCELERATECONDTION)
						{   
							mNum = mNum + 1;
							//실시간으로 값이 증가하는것을 보여주기위해 리스너에서 즉각적으로 출력하여 준다.
							mValueText.setText(String.format("%d",mNum));	
							//다시 처음부터 누적시키기위해서 값을 초기화 한다.
							mAccelerateValue = 0;
						}
					}
					else if(mStatus == POWERON){
						if(mTime == 0)
						{
							mTime++;
							mBeforValue[0] = (int)event.values[0];
							mBeforValue[1] = (int)event.values[1];
							mBeforValue[2] = (int)event.values[2];
						}
						else
						{
							mTime = 0;
							mAfterValue[0] = (int)event.values[0];
							mAfterValue[1] = (int)event.values[1];
							mAfterValue[2] = (int)event.values[2];
						}
						//가속도 변화의 값이 지속적으로 누적 되어 진다.
						mAccelerateValue += Math.abs(mBeforValue[0] -mAfterValue[0]);
						mAccelerateValue += Math.abs(mBeforValue[1] -mAfterValue[1]);
						//실시간으로 값이 증가하는것을 보여주기위해 리스너에서 즉각적으로 출력하여 준다.
						mValueText.setText(String.format("%d",mAccelerateValue));
					}
					break;
				}
			}
		}	
	};

	//손가락 터치 측정을 위한 리스너 이다.
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub	
		if(mStatus == FINGERTOUCHON){
			//터치 이벤트가 발생 했고 터치 측정모드 일때만 동작 한다.
			if(event.getAction() == MotionEvent.ACTION_DOWN) {
				mFingerTouchValue++;
				//실시간으로 값이 증가하는것을 보여주기위해 리스너에서 즉각적으로 출력하여 준다.
				mValueText.setText(String.format("%d",mFingerTouchValue));
				return true;
			}
			return false;
		}
		else if(mStatus == FINGERDISTANCEON){
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
	    		arVertex.add(new Vertex(event.getX(), event.getY(), false));
	    		if(arVertex.size() >1){
	    			mFingerDistanceValue += processDistance(
    						arVertex.get(arVertex.size()-2).x, arVertex.get(arVertex.size()-2).y
    						,arVertex.get(arVertex.size()-1).x,arVertex.get(arVertex.size()-1).y
    						);
	    		}		
				//실시간으로 값이 증가하는것을 보여주기위해 리스너에서 즉각적으로 출력하여 준다.
				mValueText.setText(String.format("%d",mFingerDistanceValue));
	    		return true;
	    	}
	    	if (event.getAction() == MotionEvent.ACTION_MOVE) {
	    		arVertex.add(new Vertex(event.getX(), event.getY(), true));
	    		if(arVertex.size() >1){
	    			mFingerDistanceValue += processDistance(
    						arVertex.get(arVertex.size()-2).x, arVertex.get(arVertex.size()-2).y
    						,arVertex.get(arVertex.size()-1).x,arVertex.get(arVertex.size()-1).y
    						);
	    		}
				//실시간으로 값이 증가하는것을 보여주기위해 리스너에서 즉각적으로 출력하여 준다.
				mValueText.setText(String.format("%d",mFingerDistanceValue));
	    		return true;
			}
			return false;
		}
		else{
			return false;
		}
		
	}
	

    /* 
     * 손가락 거리 측정에 사용하는
     * 거리를 계산하는 함수 이다. 
     */
    public int processDistance(float srcX, float srcY, float desX, float desY)
    {
    	int result = 0;
    	
    	result = (int)Math.sqrt(Math.pow(Math.abs(srcX-desX),2) + Math.pow(Math.abs(srcY-desY),2));

    	return result;
    }
    
    // 핸들러 이다.
	Handler mTimerHandler = new Handler() {

		public void handleMessage(Message msg){
			String mDialogMessage="";
			//처리 결과를 반영 하라는 메시지이다.
			if(msg.what == PROCESSRESULT){
				mWriteProgressDialog.setProgress(msg.arg1);
				//main UI의 다이얼 로그를 정지 시킨다.
				if(msg.arg1 >= 100){
					dismissDialogSafely(DIALOG_PROBABILITY_PROGRESS);
					String openMsg = "";
					if(mChanceResult[STEP_INDEX] >= (int)(Math.random()*1000)) {
						//히든 오픈
						row1col1Flag = true;
						//장수도감을 위해서 프레퍼런스에 기록한다.
						mEdit.putBoolean("gwanu_prefer_info", true);
						mEdit.commit();
						openMsg +=" 관우오픈!!";
					}
					if(mChanceResult[SPEED_INDEX] >= (int)(Math.random()*300)) {
						//히든오픈
						row1col2Flag = true;
						mEdit.putBoolean("yeopo_prefer_info", true);
						mEdit.commit();
						openMsg +=" 여포오픈!!";
					}
					if(mChanceResult[BOOSTER_INDEX] >= (int)(Math.random()*5000)) {
						//히든오픈
						row1col3Flag = true;
						mEdit.putBoolean("joun_prefer_info", true);
						mEdit.commit();
						openMsg +=" 조운오픈!!";
					}
					if(mChanceResult[STEP_INDEX] >= (int)(Math.random()*1000)) {
						//히든 오픈
						row2col3Flag = true;
						mEdit.putBoolean("macho_prefer_info", true);
						mEdit.commit();
						openMsg +=" 마초오픈!!";
					}
					if(mChanceResult[SPEED_INDEX]+mCycle*3 >= (int)(Math.random()*300)) {
						//히든오픈
						row3col1Flag = true;
						mEdit.putBoolean("yubi_prefer_info", true);
						mEdit.commit();
						openMsg +=" 유비오픈!!";
					}
					if(mChanceResult[BOOSTER_INDEX]+mCycle*100 >= (int)(Math.random()*5000)) {
						//히든오픈
						row3col2Flag = true;
						mEdit.putBoolean("jangbi_prefer_info", true);
						mEdit.commit();
						openMsg +=" 장비오픈!!";
					}
					if(mChanceResult[STEP_INDEX]+mCycle*10 >= (int)(Math.random()*1000)) {
						//히든 오픈
						row3col3Flag = true;
						mEdit.putBoolean("hwangchung_prefer_info", true);
						mEdit.commit();
						openMsg +=" 황충오픈!!";
					}
					if(mChanceResult[FINGELDISTANCEINDEX]+mCycle*1000  >= (int)(Math.random()*100000)) {
						row2col1Flag = true;
						mEdit.putBoolean("hahudon_prefer_info", true);
						mEdit.commit();
						openMsg +="하후돈오픈!!";
					}
			
					mDialogMessage=openMsg;

					//찬스를 적용했으면 측정 최대치 값을 초기화 한다.
					mMeasureResult[SPEED_INDEX] =0;
					mMeasureResult[BOOSTER_INDEX] =0;
					mMeasureResult[STEP_INDEX] =0;
					mMeasureResult[FINGELDISTANCEINDEX] = 0;
					showMesureText();

					showMessageDialog(mDialogMessage, true);
				}
				return;
			}
			//준비 시간은 모든 측정에서 공통적으로 수행 되어진다.
			//준비시간이 끝나야 다음의 code가 수행되어 진다.
			if(mReadyTime >0){
				mPool.play(mTimeSound, 1, 1, 0, 0, 1);

				mMessageText1.setText("");
				mValueText.setText("Ready");
				mMesaageText2.setText("시작까지 남은 시간");
				mNowTimeText.setText(Integer.toString(mReadyTime));
				//초기값 3초에서 1초씩 줄여 나간다.
				mReadyTime--;
				//받은 msg.what대로 계속 반복해줘야 준비시간이 끝난 다음 정상적으로 다음 작업을 수행한다.
				mTimerHandler.sendEmptyMessageDelayed(msg.what,1000);
				return;
			}
			else if(mReadyTime == 0){
				// 시작할때 한번만 진동을 처리한다.
				Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
				vibrator.vibrate(500);
				mMessageText1.setText("측정 값");
				mMesaageText2.setText("남은 시간");
				//한번만 이 구문을 수행하기 위해서 이러한 처리를 수행 한다.
				mReadyTime--; 
			}

			//10초 동안 카운트 다운 한다.
			if (mMeasureTime != 0) {	
				/*
				 *  현재의 측정 상태를 각 측정 모드에 맞게 설정한다.
				 *  이곳에서 변경해야 준비 시간에는 측정이 잃어나지 않는다.
				 */
				mStatus = msg.what;

				//측정시간을 감소시키고 감소된 시간을 화면에 표시해 준다.
				mMeasureTime--;
				mNowTimeText.setText(Integer.toString(mMeasureTime));
				//1초가 지난 후에 똑같은 메시지를 똑같이 전송 한다.
				mTimerHandler.sendEmptyMessageDelayed(msg.what,1000);
				mPool.play(mTimeSound, 1, 1, 0, 0, 1);
			} 
			else {
				//측정이 끝났음을 알려 준다.
				Toast.makeText(measureActivity.this, 
						"측정이 끝났습니다.", Toast.LENGTH_LONG).show();
				Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
				vibrator.vibrate(500);
				/*
				 *  현재의 측정 상태를 비측정 상태로 만든다.
				 */
				mStatus = ALLOFF;
				//버튼을 다시 모두 활성화 시켜 준다.
				mShakeButton.setVisibility(View.VISIBLE);
				mPowerButton.setVisibility(View.VISIBLE);
				mFingerTouchButton.setVisibility(View.VISIBLE);
				mFingerDistanceButton.setVisibility(View.VISIBLE);
				mApplyButton.setVisibility(View.VISIBLE);

				//준비시간을 다시 처음 3초로 초기화 시킨다.
				//측정 시간의 초기화는 각각의 측정마다 다르게 때문에 측정 버튼을 시작할떄 초기화 하도록 한다.
				mReadyTime = 3;

				//각각의 측정에 맞는 메시지대로 동작하게 처리한다.
				if(msg.what == SHAKEON){
					//흔들기한 횟수를 일단 저장한다. 재 측정할떄 지워지기 떄문에
					//변경은 이전값이 측정한 값보다 클 경우만 해당된다.
					//최고 기록은 게임에 실제로 반영하기 전까지는 보존해준다 
					if(mMeasureResult[SPEED_INDEX] < mNum){
						mMeasureResult[SPEED_INDEX] = mNum;
						showMesureText();
					}
				}
				else if(msg.what == POWERON){
					//흔들기 파워를 일단 저장한다. 재 측정할떄 지워지기 떄문에
					//변경은 이전값이 측정한 값보다 클 경우만 해당된다.
					//최고 기록은 게임에 실제로 반영하기 전까지는 보존해준다 
					if(mMeasureResult[BOOSTER_INDEX] < mAccelerateValue){
						mMeasureResult[BOOSTER_INDEX] = mAccelerateValue;
						showMesureText();
					}
				}
				else if(msg.what == FINGERTOUCHON){
					//터치 횟수를 일단 저장한다. 재 측정할떄 지워지기 떄문에
					//변경은 이전값이 측정한 값보다 클 경우만 해당된다.
					//최고 기록은 게임에 실제로 반영하기 전까지는 보존해준다 
					if(mMeasureResult[STEP_INDEX] < mFingerTouchValue){
						mMeasureResult[STEP_INDEX] = mFingerTouchValue;
						showMesureText();
					}
				}
				else if(msg.what == FINGERDISTANCEON){
					//터치 거리를 일단 저장한다. 재 측정할때 지워지기 때문에
					//변경은 이전값이 측정한 값보다 클 경우만 해당된다.
					//최고 기록은 게임에 실제로 반영하기 전까지는 보존해준다.
					if(mMeasureResult[FINGELDISTANCEINDEX] < mFingerDistanceValue){
						mMeasureResult[FINGELDISTANCEINDEX] = mFingerDistanceValue;
						showMesureText();
					}
					
				}
			}
			/*	
			//각각의 측정에 맞는 메시지대로 동작하게 처리한다.
			if(msg.what == SHAKEON){
			}
			else if(msg.what == POWERON){

			}
			else if(msg.what == FINGERTOUCHON){

			}*/
		}
	};

	// 측정 결과를 화면 상단에 표시한다.
	public void showMesureText(){
		mMeasureText.setText(String.format("흔든횟수 :%d, 흔든파워 :%d, 터치횟수 :%d 거리 : %d",
				mMeasureResult[0],mMeasureResult[1],mMeasureResult[2],mMeasureResult[FINGELDISTANCEINDEX]));
	}
	/*
	 * 실제적으로 다이얼로그 창을 생성하는 부분이다.
	 * 이렇게 한번 다이얼로그를 생성해놓고 재사용하면 시스템의 성능을 향상 시킬 수 있다.
	 */
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_PROBABILITY_PROGRESS:
			mWriteProgressDialog = new ProgressDialog(this);
			mWriteProgressDialog.setIcon(android.R.drawable.ic_dialog_info);
			mWriteProgressDialog.setTitle(getString(R.string.progress_title));
			mWriteProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mWriteProgressDialog.setCancelable(false);
			mWriteProgressDialog.setMessage(
					getString(R.string.write_progress_message));
			return mWriteProgressDialog;
		}
		return null;
	}

	public void showDialogSafely(final int id) {
		// 강제적으로 UI Thread와 동기화 시키는 쓰레드 이다.
		// 즉 화면의 표시를 결정하기 위해 사용되어 진다.
		runOnUiThread(new Runnable() {
			public void run() {
				try {
					// 다이얼로그 인스턴스를 한번 생성하고 지속시켜서 매번 그것을 재사용 한다.
					// 어떤 다이얼로그가 불려지는지 정확히 알기 위해서는 onCreateDialog 핸들러를 봐야 한다.
					showDialog(id);

				} catch (BadTokenException e) {
					Log.w(TAG,
							"Could not display dialog with id " + id, e);
				} catch (IllegalStateException e) {
					Log.w(TAG,
							"Could not display dialog with id " + id, e);
				}
			}
		});
	}

	// 처리 프로그래스 바의 딜레이를 담당하는 UI제어 관련 Thread이다.
	public void saveProgress(int arTime) {
		showDialogSafely(DIALOG_PROBABILITY_PROGRESS);

		//	dismissDialogSafely(DIALOG_PROBABILITY_PROGRESS);
		// 결과 메시지를 처리하여 준다. 성공 했는지 실패 했는지를..
		//	showMessageDialog(0, true);
	}
	/**
	 * 측정 처리 결과 적용에 대한 메시지를 띠워 준다.
	 */
	public void showMessageDialog(final CharSequence message, final boolean success) {
		runOnUiThread(new Runnable() {
			public void run() {
				AlertDialog dialog = null;
				AlertDialog.Builder builder = new AlertDialog.Builder(measureActivity.this);
				builder.setMessage(message);
				builder.setNegativeButton(measureActivity.this.getString(R.string.ok), null);
				builder.setIcon(success ? android.R.drawable.ic_dialog_info :
					android.R.drawable.ic_dialog_alert);
				builder.setTitle(success ? R.string.success : R.string.error);
				builder.setPositiveButton("acepte",new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						Intent intent = new Intent();
						intent.putExtra("row1col1", row1col1Flag);
						intent.putExtra("row1col2", row1col2Flag);
						intent.putExtra("row1col3", row1col3Flag);
						intent.putExtra("row2col1", row2col1Flag);
						intent.putExtra("row2col2", row2col2Flag);
						intent.putExtra("row2col3", row2col3Flag);
						intent.putExtra("row3col1", row3col1Flag);
						intent.putExtra("row3col2", row3col2Flag);
						intent.putExtra("row3col3", row3col3Flag);
						
						mChanceResult[SPEED_INDEX] =0;
						mChanceResult[BOOSTER_INDEX] =0;
						mChanceResult[STEP_INDEX] =0;
						setResult(RESULT_OK, intent);
						finish();
					}
				});
				builder.setNegativeButton("cancel",new DialogInterface.OnClickListener() {

					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						//취소를 했기 때문에 확률 결과값을 초기화 한다.
						mChanceResult[SPEED_INDEX] =0;
						mChanceResult[BOOSTER_INDEX] =0;
						mChanceResult[STEP_INDEX] =0;
						mChanceResult[FINGELDISTANCEINDEX] = 0;
						
						row1col1Flag = false;
						row1col2Flag = false;
						row1col3Flag = false;
						row2col1Flag = false;
						row2col2Flag = true;
						row2col3Flag = false;
						row3col1Flag = false;
						row3col2Flag = false;
						row3col3Flag = false;
						//취소 했다는 메시지를 출력한다.
						Toast.makeText(measureActivity.this, 
								R.string.cancel_massage, Toast.LENGTH_SHORT).show();
					}
				});
				dialog = builder.create();
				dialog.show();
			}
		});
	}
	/* Dialog를 종료해 준다.*/
	public void dismissDialogSafely(final int id) {
		runOnUiThread(new Runnable() {
			public void run() {
				try {
					dismissDialog(id);
				} catch (IllegalArgumentException e) {
					// 에러 핸들링 코드를 작성 한다.
				}
			}
		});
	}
	class processResultThread extends Thread {
		int mValue = 0;
		int mChanceSpeed = mMeasureResult[SPEED_INDEX];
		int mChanceBooster = mMeasureResult[BOOSTER_INDEX];
		int mChanceStep = mMeasureResult[STEP_INDEX];
		int mChanceFingerDistance = mMeasureResult[FINGELDISTANCEINDEX];
		int cycle=0;
		public void run(){
			while(mValue < 100){
				// 확률적 계산의 반복 횟수는 
				// best case 10 cycle, worst case 1 cycle
				mValue += (int)(Math.random()*100+10);
				cycle +=1;
				mCycle = cycle;

				mChanceResult[SPEED_INDEX] = mChanceSpeed;
				mChanceResult[BOOSTER_INDEX] = mChanceBooster;
				mChanceResult[STEP_INDEX] = mChanceStep;
				mChanceResult[FINGELDISTANCEINDEX] = mChanceFingerDistance;

				Message msg = mTimerHandler.obtainMessage();
				msg.what = PROCESSRESULT;
				msg.arg1 = mValue;
				msg.arg2 = cycle;

				mTimerHandler.sendMessage(msg);
				//노가다 방지용의 딜레이
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	// 정점 하나에 대한 정보를 가지는 클래스
	public class Vertex {
		Vertex(float ax, float ay, boolean ad) {
			x = ax;
			y = ay;
			Draw = ad;
		}
		float x;
		float y;
		boolean Draw;
	}
}
